//------------------------------------------------------------------------------
// <copyright file="HeroViewModelBase.cs" company="Damian Antonowicz">
//       copyright © 2010 Damian Antonowicz
// </copyright>
// <author>Damian Antonowicz</author>
// <email>poczta@damianantonowicz.pl</email>
//------------------------------------------------------------------------------

using System;
using DotBeer.Business.Entities;
using DotBeer.Business.Components;
using DotBeer.UI.WPFClient.Commands;
using System.Diagnostics;
using System.Collections.ObjectModel;
using System.Collections.Specialized;
using DotBeer.Business.Components.Exceptions;
using DAnton.Utilities.Extensions;

namespace DotBeer.UI.WPFClient.ViewModels
{
    public abstract class HeroViewModelBase : ViewModelBase
    {
        #region private members

        Authors authors;
        HeroesCollection heroesCollection;

        DelegateCommand copyItemBuildCommand;
        DelegateCommand copySkillBuildCommand;
        DelegateCommand<string> loadHeroByAuthorNameCommand;
        DelegateCommand<string> loadHeroByHeroNameCommand;

        protected Hero hero;

        #endregion

        #region properties

        public Hero Hero
        {
            get { return this.hero; }
        }

        public string AuthorName
        {
            get
            {
                if (this.hero != null)
                    return this.hero.Author;
                else return "";
            }
            set 
            {
                if (value != null && value != "")
                {
                    this.hero.Author = value;
                }

                this.OnPropertyChanged("AuthorName");
            }
        }

        public ItemBuild CurrentItemBuild
        {
            get { return this.hero.CurrentItemBuild; }
            set
            {
                this.hero.CurrentItemBuild = value;
                this.OnPropertyChanged("CurrentItemBuild");
            }
        }

        public SkillBuild CurrentSkillBuild
        {
            get { return this.hero.CurrentSkillBuild; }
            set
            {
                this.hero.CurrentSkillBuild = value;
                this.OnPropertyChanged("CurrentSkillBuild");
            }
        }

        public ObservableCollection<string> Authors
        {
            get { return this.authors; }
        }

        public ObservableCollection<HeroTavern> Heroes
        {
            get { return this.heroesCollection.Heroes; }
        }

        public string WindowTitle
        {
            get { return this.hero == null ? "DotBeer" : String.Format("{0} - DotBeer", this.hero.Name); }
        }

        public event EventHandler<PropertyChangingEventArgs> PropertyChanging;

        #endregion

        #region commands

        public DelegateCommand<string> LoadHeroByHeroNameCommand
        {
            get
            {
                if (this.loadHeroByHeroNameCommand == null)
                    this.loadHeroByHeroNameCommand = new DelegateCommand<string>(this.LoadHeroByHeroName);

                return this.loadHeroByHeroNameCommand;
            }
        }

        public DelegateCommand<string> LoadHeroByAuthorNameCommand
        {
            get
            {
                if (this.loadHeroByAuthorNameCommand == null)
                    this.loadHeroByAuthorNameCommand = new DelegateCommand<string>(this.LoadHeroByAuthorName);

                return this.loadHeroByAuthorNameCommand;
            }
        }

        public DelegateCommand CopyItemBuildCommand
        {
            get
            {
                if (copyItemBuildCommand == null)
                    copyItemBuildCommand = new DelegateCommand(CopyItemBuildToClipboard, CanCopyBuild);

                return copyItemBuildCommand;
            }
        }

        public DelegateCommand CopySkillBuildCommand
        {
            get
            {
                if (copySkillBuildCommand == null)
                    copySkillBuildCommand = new DelegateCommand(CopySkillBuildToClipboard, CanCopyBuild);

                return copySkillBuildCommand;
            }
        }

        #endregion

        #region constructors

        public HeroViewModelBase()
        {
            this.heroesCollection = HeroesCollectionComponent.Load();
            this.authors = DotBeer.Business.Entities.Authors.Instance;
            this.authors.CollectionChanged += new NotifyCollectionChangedEventHandler(authors_CollectionChanged);
        }

        #endregion

        #region private methods

        protected void LoadHeroByHeroName(string heroName)
        {
            this.LoadHero(() => HeroComponent.Load(heroName), heroName);
        }

        protected void LoadHeroByAuthorName(string authorName)
        {
            this.LoadHero(this.hero.Name, authorName);
        }

        protected void LoadHero(string heroName, string authorName)
        {
            this.LoadHero(() => HeroComponent.Load(heroName, authorName), heroName);
        }

        protected void LoadHero(Func<Hero> loadMethod, string heroName)
        {
            this.OnPropertyChanging("Hero");

            this.hero = null;

            try
            {
                this.hero = loadMethod();
            }
            catch (Exception ex)
            {
                HandleExceptions.UIPolicy(ex);
            }

            if (hero == null)
            {
                this.hero = HeroComponent.LoadDefaultHero(heroName);
            }

            if (this.hero.ItemBuilds.Count > 0)
            {
                this.hero.CurrentItemBuild = this.hero.ItemBuilds[0];
                this.OnPropertyChanged("CurrentItemBuild");
            }

            if (this.hero.SkillBuilds.Count > 0)
            {
                this.hero.CurrentSkillBuild = this.hero.SkillBuilds[0];
                this.OnPropertyChanged("CurrentSkillBuild");
            }

            this.OnPropertyChanged("Hero");
            this.OnPropertyChanged("AuthorName");
            this.OnPropertyChanged("WindowTitle");
        }

        private void CopyItemBuildToClipboard()
        {
            HeroComponent.CopyItemBuildToClipboard(this.hero);
        }

        private void CopySkillBuildToClipboard()
        {
            HeroComponent.CopySkillBuildToClipboard(this.hero);
        }

        private bool CanCopyBuild()
        {
            return hero != null;
        }

        private void OnPropertyChanging(string propertyName)
        {
            if (PropertyChanging != null)
                PropertyChanging(this, new PropertyChangingEventArgs(propertyName));
        }

        void authors_CollectionChanged(object sender, NotifyCollectionChangedEventArgs e)
        {
            this.OnPropertyChanged("AuthorName");
        }

        #endregion
    }
}
